package com.android.baseconfig.common.utils;

import android.content.Context;
import android.graphics.Bitmap;
import android.os.Build;
import android.os.Environment;
import android.os.StatFs;
import android.text.TextUtils;
import android.text.format.Formatter;
import android.util.Log;

import com.android.baseconfig.base.BaseConfigApplication;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Objects;


/**
 * @author lei
 * @date 2017/5/11
 */
public class FileUtil {
    private static final String TAG = FileUtil.class.getName();
    /**
     * SD卡外部存储路径
     */
    public static String ROOT_DIR = "苏泊尔";
    public static final String DOWNLOAD_DIR = "Download";
    public static final String CACHE_DIR = "cache";
    public static final String ICON_DIR = "icon";
    public static final String IMAGE_DIR = "image";
    public static final String IMAGE_USER_DIR = "user_image";

    /**
     * 判断SD卡是否挂载
     */
    public static boolean isSDCardAvailable() {
        return Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState());
    }

    /**
     * 获取下载目录
     */
    public static String getDownloadDir() {
        return getDir(DOWNLOAD_DIR);
    }

    /**
     * 获取缓存目录
     */
    public static String getCacheDir() {
        return getDir(CACHE_DIR);
    }

    /**
     * 获取icon目录
     */
    public static String getIconDir() {
        return getDir(ICON_DIR);
    }

    /**
     * 获取图片目录
     */
    public static String getImageDir() {
        return getDir(IMAGE_DIR);
    }

    /**
     * 用户图片目录
     */
    public static String getImageUserDir() {
        return getDir(IMAGE_USER_DIR);
    }

    /**
     * 获取应用目录，当SD卡存在时，获取SD卡上的目录，当SD卡不存在时，获取应用的cache目录
     */
    public static String getDir(String name) {
        StringBuilder sb = new StringBuilder();
        if (isSDCardAvailable()) {
            sb.append(getExternalStoragePath());
        } else {
            sb.append(getCachePath());
        }
        sb.append(File.separator);
        sb.append(name);
        sb.append(File.separator);
        String path = sb.toString();
        if (createDirs(path)) {
            return path;
        } else {
            return null;
        }
    }

    /**
     * 获取SD下的应用目录
     */
    public static String getExternalStoragePath() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            File externalFileRootDir =
                    BaseConfigApplication.getInstance().getExternalFilesDir(null);
            if (externalFileRootDir == null) {
                externalFileRootDir = BaseConfigApplication.getInstance().getFilesDir();
                return Objects.requireNonNull(externalFileRootDir).getAbsolutePath();
            }
            do {
                externalFileRootDir = Objects.requireNonNull(externalFileRootDir).getParentFile();
            } while (Objects.requireNonNull(externalFileRootDir).getAbsolutePath().contains("/Android"));

            return Objects.requireNonNull(externalFileRootDir).getAbsolutePath();
        } else {
            if (isSDCardAvailable()) {
                return Environment.getExternalStorageDirectory().getAbsolutePath();
            } else {
                return getCachePath();
            }
        }
    }

    /**
     * 获取应用的cache目录
     */
    public static String getCachePath() {
        File f = BaseConfigApplication.getInstance().getCacheDir();
        if (null == f) {
            return null;
        } else {
            return f.getAbsolutePath();
        }
    }

    /**
     * 创建文件夹
     */
    public static boolean createDirs(String dirPath) {
        File file = new File(dirPath);
        if (!file.exists() || !file.isDirectory()) {
            // if (!file.getParentFile().exists()) {
            //     file.getParentFile().getParentFile().mkdirs();
            //     file.getParentFile().mkdirs();
            // }
            return file.mkdirs();
        }
        return true;
    }

    public static void closeIoStream(final Closeable closeable) {
        if (closeable == null) {
            return;
        }
        try {
            closeable.close();
        } catch (IOException ex) {
            Log.e(FileUtil.TAG, "close fail.");
        }
    }

    public static boolean copyFile(String src, String dst) {

        if (null == src || src.isEmpty()) {
            Log.e(TAG + "--639", "src is null");
            return false;
        }

        if (null == dst || dst.isEmpty()) {
            Log.e(TAG + "--645", "dst is null");
            return false;
        }

        FileInputStream fis = null;
        BufferedInputStream bis = null;
        FileOutputStream fos = null;
        BufferedOutputStream bos = null;

        try {
            fis = new FileInputStream(src);
            bis = new BufferedInputStream(fis);

            fos = new FileOutputStream(dst);
            bos = new BufferedOutputStream(fos);

            byte[] buf = new byte[1024 * 1024];

            int realenth = -1;

            while ((realenth = bis.read(buf)) != -1) {
                bos.write(buf, 0, realenth);
            }

            bos.flush();

            fos.close();
            fis.close();
            if (FileMD5.getFileMD5String(new File(src)).equals(FileMD5.getFileMD5String(new File(dst)))) {
                return true;
            }

        } catch (FileNotFoundException e) {
            Log.e(TAG + "--681", "WRONG when move file from=" + src + ", to=" + dst);
        } catch (IOException e) {
            Log.e(TAG + "--685", "WRONG when move file from=" + src + ", to=" + dst);
        } finally {
            closeIoStream(fis);
            closeIoStream(bis);
            closeIoStream(bos);
            closeIoStream(fos);
        }

        return false;
    }

    /**
     * 把数据写入文件
     *
     * @param content  数据流
     * @param path     文件路径
     * @param recreate 如果文件存在，是否需要删除重建
     * @return 是否写入成功
     */
    public static boolean writeFile(byte[] content, String path, boolean recreate) {
        boolean res = false;
        File f = new File(path);
        FileOutputStream fos = null;
        try {
            if (recreate && f.exists()) {
                f.delete();
            }
            if (!f.exists() && null != content) {
                File parentFile = new File(f.getParent());
                parentFile.mkdirs();
                int count = -1;
                byte[] buffer = new byte[1024];
                fos = new FileOutputStream(f);
                fos.write(content);
                res = true;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            close(fos);
        }
        return res;
    }

    /**
     * 把数据写入文件
     *
     * @param is       数据流
     * @param path     文件路径
     * @param recreate 如果文件存在，是否需要删除重建
     * @return 是否写入成功
     */
    public static boolean writeFile(InputStream is, String path, boolean recreate) {
        boolean res = false;
        File f = new File(path);
        FileOutputStream fos = null;
        try {
            if (recreate && f.exists()) {
                f.delete();
            }
            if (!f.exists() && null != is) {
                File parentFile = new File(f.getParent());
                parentFile.mkdirs();
                int count = -1;
                byte[] buffer = new byte[1024];
                fos = new FileOutputStream(f);
                while ((count = is.read(buffer)) != -1) {
                    fos.write(buffer, 0, count);
                }
                res = true;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            close(fos);
            close(is);
        }
        return res;
    }

    /**
     * 把字符串数据写入文件
     *
     * @param content 需要写入的字符串
     * @param path    文件路径名称
     * @param append  是否以添加的模式写入
     * @return 是否写入成功
     */
    /*public static boolean writeFile(byte[] content, String path, boolean append) {
        boolean res = false;
        File f = new File(path);
        RandomAccessFile raf = null;
        try {
            if (f.exists()) {
                if (!append) {
                    f.delete();
                    f.createNewFile();
                }
            } else {
                f.createNewFile();
            }
            if (f.canWrite()) {
                raf = new RandomAccessFile(f, "rw");
                raf.seek(raf.length());
                raf.write(content);
                res = true;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            close(raf);
        }
        return res;
    }*/

    /**
     * 把字符串数据写入文件
     *
     * @param content  需要写入的字符串
     * @param path     文件路径名称
     * @param recreate 如果文件存在，是否需要删除重建
     * @return 是否写入成功
     */
    public static boolean writeFile(String content, String path, boolean recreate) {
        return writeFile(content.getBytes(), path, recreate);
    }

    /**
     * 关闭流
     */
    public static boolean close(Closeable io) {
        if (io != null) {
            try {
                io.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return true;
    }

    public static File createSDDir(String dirName) throws IOException {
        File dir = new File(getScreenshotPath() + dirName);
        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
            Log.i(TAG, "createSDDir:" + dir.getAbsolutePath());
            Log.i(TAG, "createSDDir:" + dir.mkdir());
        }
        return dir;
    }

    public static boolean createSubFolder(String parentPath, String sonName) {
        if (null == parentPath || parentPath.isEmpty()) {
            // Log.e(TAG + "--537", "parentPath = " + parentPath);
            return false;
        }

        if (null == sonName || sonName.isEmpty()) {
            // Log.e(TAG + "--543", "sonName = " + sonName);
            return false;
        }

        String newDir = parentPath + File.pathSeparator + sonName;
        if (parentPath.endsWith(File.pathSeparator)) {
            newDir = parentPath + sonName;
        }

        File afile = new File(newDir);
        if (!afile.exists()) {
            return afile.mkdirs();
        }

        return false;
    }

    public static void deleteDir() {
        File dir = new File(getScreenshotPath());
        if (!dir.exists() || !dir.isDirectory()) {

            return;
        }

        for (File file : dir.listFiles()) {
            if (file.isFile()) {

                Log.d(TAG, "file.delete()=" + file.delete()); // 删除所有文件

            } else if (file.isDirectory()) {

                deleteDir(); // 递规的方式删除文件夹
            }
        }
        Log.d(TAG, "dir.delete()=" + dir.delete());// 删除目录本身

    }

    public static boolean deleteDir(String path) {
        File dir = new File(path);
        if (!dir.exists() || !dir.isDirectory()) {
            return false;
        }
        boolean isSuccess = false;
        for (File file : dir.listFiles()) {
            if (file.isFile()) {
                String fileName = file.getName();
                isSuccess = file.delete();
                Log.d(TAG, "delete file " + fileName + (isSuccess ? " success" : " fail")); //
                // 删除所有文件
                if (!isSuccess) {
                    return false;
                }
            } else if (file.isDirectory()) {
                isSuccess = deleteDir(file.getAbsolutePath()); // 递规的方式删除文件夹
                if (!isSuccess) {
                    return false;
                }
            }
        }
        String dirName = dir.getName();
        isSuccess = dir.delete();
        Log.d(TAG, "delete dir " + File.separator + dirName + (isSuccess ? " success" : " fail")); // 删除所有文件
        return isSuccess;
    }

    /**
     * 删除文件
     *
     * @param src 文件路径地址
     * @return
     */
    public static boolean deleteFile(String src) {
        if (TextUtils.isEmpty(src)) {
            Log.d(TAG + "--892", "src is null");
            return false;
        }

        File afile = new File(src);

        return afile.delete();
    }

    public static void deleteFile(File file) {
        if (null == file) {
            return;
        }

        if (file.exists() && file.isDirectory()) {
            File[] subFiles = file.listFiles();

            if (null == subFiles || 0 == subFiles.length) {
                // 删除空目录
                Log.d(TAG, "blank directory file.delete()=" + file.delete());
            } else {
                for (File oneFile : subFiles) {
                    deleteFile(oneFile);
                }

                String[] tmpSubs = file.list();
                if (null == tmpSubs || 0 == tmpSubs.length) {
                    // 如果这个目录空了 就直接删除
                    Log.d(TAG, "a directory file.delete()=" + file.delete());
                }
            }
        }

        if (file.exists() && file.isFile()) {
            if (!file.delete()) {
                Log.d(TAG, "File delete failed!");
            }
        }
    }

    /**
     * 根据路径获取手机可用存储大小
     *
     * @param mContext android 上下文对象
     * @param path     查询路径
     * @return
     */
    public static long getAvailableMemory(Context mContext, File path) {
        // 获得一个磁盘状态对象
        StatFs stat = new StatFs(path.getPath());

        long blockSize = stat.getBlockSize(); // 获得一个扇区的大小

        long availableBlocks = stat.getAvailableBlocks(); // 获得可用的扇区数量

        // 可用空间
        long availableMemory = availableBlocks * blockSize;

        return availableMemory;
    }

    public static String getParentPath(String fullPath) {
        if (fullPath == null) {
            return null;
        }

        File afile = new File(fullPath);
        if (afile.isFile()) {
            return afile.getParent();
        } else {
            return afile.getAbsolutePath();
        }
    }

    /**
     * 根据路径获取手机存储状态
     *
     * @param path
     * @return
     */
    public static String getMemoryInfo(Context mContext, File path) {
        // 获得一个磁盘状态对象
        StatFs stat = new StatFs(path.getPath());

        long blockSize = stat.getBlockSize(); // 获得一个扇区的大小

        long totalBlocks = stat.getBlockCount(); // 获得扇区的总数

        long availableBlocks = stat.getAvailableBlocks(); // 获得可用的扇区数量

        // 总空间
        String totalMemory = Formatter.formatFileSize(mContext, totalBlocks * blockSize);
        // 可用空间
        String availableMemory = Formatter.formatFileSize(mContext, availableBlocks * blockSize);

        return "TotalMemory: " + totalMemory + " AvailableMemory: " + availableMemory;
    }

    public static String getSDPath() {

        File sdDir = null;
        boolean sdCardExist =
                Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED); //
        // 判断sd卡是否存在
        if (sdCardExist) {
            sdDir = Environment.getExternalStorageDirectory();// 获取跟目录
        }

        if (null != sdDir) {
            try {
                return sdDir.getCanonicalPath();
            } catch (IOException e) {
                return "";
            }
        } else {
            return "";
        }
    }

    public static String getScreenshotPath() {
        return Environment.getExternalStorageDirectory() + File.separator + "home" + File.separator + "screenshot" + File.separator;
    }

    public static boolean isFileExist(final String fileName) {
        final File file = new File(fileName);
        file.isFile();
        return file.exists();
    }

    public static boolean isNoneFileExsit(List<String> filePaths) {
        for (String filePath : filePaths) {
            File file = new File(filePath);
            if (file.exists()) {
                return false;
            }
        }
        return true;
    }

    public static boolean moveFileInPhone(String src, String dst) {
        if (copyFile(src, dst)) {
            if (deleteFile(src)) {
                return true;
            } else {
                return deleteFile(dst) ? false : true;
            }
        } else {
            return false;
        }
    }

    /**
     * 将bitmap保存到本地存储路径下
     *
     * @param bm
     * @param picName
     */
    public static void saveBitmap(Bitmap bm, String picName) {

        FileOutputStream out = null;

        try {
            if (!isFileExist("")) {
                createSDDir("");
            }
            File f = new File(getScreenshotPath(), picName + ".JPEG");
            if (f.exists()) {
                Log.d(TAG, "f.delete()=" + f.delete());// 如果文件存在就先删除
            }
            out = new FileOutputStream(f);
            bm.compress(Bitmap.CompressFormat.JPEG, 90, out);
            out.flush();

        } catch (FileNotFoundException e) {
            Log.i(TAG, "FileNotFoundException", e);

        } catch (IOException e) {

            Log.i(TAG, "IOException", e);
        } finally {
            closeIoStream(out);

        }
    }

    public static boolean sdCardIsAvailable() {
        return Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState());
    }
}
